/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/

const { reject } = require("lodash");


/**
 * 1.初始化的时候 传入一个立即执行函数，里面有两个方法 一个成功方法，一个失败方法
 * 2.Promise 中有三种状态 分别是 成功 fulfilled  、失败 rejected 、 pending
 * 3.一旦状态确定就不可更改
 * 4.resolve 和 reject 函数是用来更改状态的
 * 5.then 方法内部就是判断 promise 内部状态，如果是成功，就调用成功回调函数，如果是失败，就调用失败回调函数
*/

// 定义Poemiseh 内部的状态为常量统一放在头部：一、是方便统一管理、修改，二、敲击时会有代码提示不易出错
const FULLFILLED = 'fullfilled';   // 成功的状态
const REJECTED = 'rejected';      // 失败的状态
const PENDING = 'pending';        // 等待的状态（默认）
class MyPromise{
  state = PENDING;                // 当前promise的状态
  successVal = undefined;         // 成功时传递的参数
  failVal = undefined;            // 失败传递的参数
  successCallbck = undefined;     //  因为是异步操作所以需要保存 then 方法发传递过来的成功方法
  failCallbck = undefined;        //  因为是异步操作所以需要保存 then 方法发传递过来的失败方法
  constructor (execution) {
    execution(this.resolve, this.reject);
  }
  // 为什么这两个成功和失败的回调函数是箭头函数：因为这是在外部调用的
  // 成功的方法
  resolve = successful =>{
    // 因为状态一旦确定就不可更改 所以在更改方法之前需要判断一下当前 Promise 的状态是否为 PENDING
    if (this.state != PENDING) return;
    // 先把当前 Promise 的内部状态更改为成功
     this.state = FULLFILLED;
    // 保存传参时 传递过来的参数
    this.successVal = successful;
    // 判断 successCallbck 成功回调韩式 是否存在，如果存在那就去调用它
    this.successCallbck && this.successCallbck(successful);
  }
  // 失败的方法
  reject = failure => {
    if (this.state != PENDING) return;
    // 先把当前 Promise 的内部状态更改为失败
     this.state = REJECTED;
     this.failVal = failure;
     // 判断 successCallbck 失败回调韩式 是否存在，如果存在那就去调用它
    this.failCallbck && this.failCallbck(failure);
  }
  then(successCallbck, failCallbck){
    if (this.state === FULLFILLED) {           // 成功时
      successCallbck(this.successVal)
    }else if(this.state === REJECTED) {     //失败时
      failCallbck(this.failVal)
    }else {                                 // 等待时
      this.successCallbck = successCallbck;
      this.failCallbck = failCallbck;
    }
  }
}

let promise = new MyPromise ( (resolve, reject) =>{
  // 成功调用
  // resolve('成功')
  // 失败调用
  setTimeout(()=>{
    reject('失败')
  },1000)
} )

promise.then( resolve => {
  console.log(resolve);
}, reject => {
  console.log(reject);
})